home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 12 / Cream of the Crop 12 (Part II) / Cream of the Crop 12 (Part II).iso / OS2 / BLT2_205.ZIP / src / blt2cx03.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-02-25  |  10.7 KB  |  379 lines

  1. /* 
  2.  *
  3.  * blt2cx03.c - 17-Oct-1995 Cornel Huth 
  4.  * This module is called by blt2demo.c
  5.  * INSERT_XB
  6.  *
  7.  */
  8.  
  9. #include "platform.h"
  10.  
  11. #ifdef ON_OS2
  12.    #include <os2.h>
  13. #endif
  14. #ifdef ON_W95
  15.    #define WIN32_LEAN_AND_MEAN
  16.    #include <windows.h>
  17. #endif
  18.  
  19. #include <stdio.h>
  20. #include <stdlib.h>
  21. #include <time.h>
  22. #include <string.h>
  23.  
  24. #ifdef ON_OS2
  25.    #include "bullet2.h"
  26. #endif
  27. #ifdef ON_W95
  28.    #include "bullet95.h"
  29. #endif
  30. #ifdef ON_DOSX
  31.    #include "bulletx.h"
  32. #endif
  33.  
  34. void cx03BuildFieldList(FIELDDESCTYPE fieldList[]);
  35.  
  36. extern CHAR *collateTable;
  37.  
  38.  
  39. int cx03() {
  40.  
  41. #pragma pack(1)
  42.  
  43. ACCESSPACK AP;
  44. DOSFILEPACK DFP;
  45. CREATEDATAPACK CDP;
  46. CREATEINDEXPACK CIP;
  47. HANDLEPACK HP;
  48. OPENPACK OP;
  49.  
  50. struct EmpRecType {
  51.  CHAR tag;              // record tag, init to SPACE, * means deleted
  52.  CHAR empID[9];         // SSN (not 0T string)
  53.  CHAR empLN[16];        // last name
  54.  CHAR empFN[16];        // first name
  55.  CHAR empHire[8];       // "YYYYMMDD" (not 0T string)
  56.  CHAR empDept[6];       // department assigned
  57. }; // 56 bytes
  58. struct EmpRecType EmpRec;
  59.  
  60. #pragma pack()
  61.  
  62. time_t startTime, endTime;
  63. int display = 0;                // display results or not flag
  64. int sameSequence = 1;           // use same random seed each time
  65. int rndSeqVar = 0;              // random "key" generated (9 digits worth)
  66.  
  67. LONG rez;                       // return value from Bullet
  68.  
  69. CHAR nameIX3[] = "$CX03.IX3";   // name of index file created
  70. ULONG indexID=0;                // handle of index file
  71. CHAR keyExpression[128];        // key expression string buffer (159 max)
  72. CHAR keyBuffer[68];             // buffer used to store/receive key values
  73.  
  74. CHAR nameData[] = "$CX03.DBF";  // name of data file created
  75. ULONG dataID=0;                 // handle of data file
  76. FIELDDESCTYPE fieldList[5];     // 5 fields used in data record
  77.  
  78. LONG recs2add;          // records to add en-masse
  79. LONG i;                 // counter
  80. CHAR tmpStr[64];        // misc stuff, non-Bullet related
  81.  
  82. printf("INSERT_XB, an all-or-nothing transaction insert into up to\n");
  83. printf("256 files (total of 512 data and index files) from a single call.\n\n");
  84.  
  85. // note that this particular example uses only a single index/data file DB
  86.  
  87. memset(fieldList,0,sizeof(fieldList));  // init unused bytes to 0 (required)
  88. cx03BuildFieldList(fieldList);
  89.  
  90. // Delete previous files from any previous run (disregard any error return)
  91.  
  92. DFP.func = DELETE_FILE_DOS;
  93. DFP.filenamePtr = nameData;
  94. rez = BULLET(&DFP);
  95. DFP.filenamePtr = nameIX3;
  96. rez = BULLET(&DFP);
  97.  
  98.  
  99. // Create the data file, a standard DBF (ID=3) as defined in fieldList above.
  100.  
  101. CDP.func = CREATE_DATA_XB;
  102. CDP.filenamePtr = nameData;
  103. CDP.noFields = 5;
  104. CDP.fieldListPtr = fieldList;
  105. CDP.fileID = 0x03;
  106. rez = BULLET(&CDP);
  107. if (rez) {
  108.    printf("Failed data file create.  Err: %li\n",rez);
  109.    goto Abend;
  110. }
  111.  
  112.  
  113. // Open the data file (required before creating an index file for it)
  114.  
  115. OP.func = OPEN_DATA_XB;
  116. OP.filenamePtr = nameData;
  117. OP.asMode = READWRITE | DENYNONE;
  118. rez = BULLET(&OP);
  119. if (rez) {
  120.    printf("Failed data file open.  Err: %li\n",rez);
  121.    goto Abend;
  122. }
  123. dataID = OP.handle;
  124.  
  125.  
  126. // Create an index file for the data file opened above.
  127. // This example uses a single, 9-byte key -- the SSN.
  128.  
  129. strcpy(keyExpression,"SSN");
  130.  
  131. CIP.func = CREATE_INDEX_XB;
  132. CIP.filenamePtr = nameIX3;
  133. CIP.keyExpPtr = keyExpression;
  134. CIP.xbLink = dataID;            // the handle of the data file
  135. CIP.sortFunction = ASCII_SORT;  // sort by ASCII order (fine for text numbers)
  136. CIP.codePage = CODEPAGE;        // code page
  137. CIP.countryCode = CTRYCODE;     // country code
  138. CIP.collatePtr = NULL;          // -- ASCII_SORT, no collate table is used
  139. CIP.nodeSize = 512;             // 512-byte node size (or 1024, 2048 bytes)
  140. rez = BULLET(&CIP);
  141. if (rez) {
  142.    printf("Failed index file create.  Err: %li\n",rez);
  143.    goto Abend;
  144. }
  145.  
  146.  
  147. // Open the index file (what we just created above).
  148.  
  149. OP.func = OPEN_INDEX_XB;
  150. OP.filenamePtr = nameIX3;
  151. OP.asMode = READWRITE | DENYNONE;
  152. OP.xbLink = dataID;
  153. rez = BULLET(&OP);
  154. if (rez) {
  155.    printf("Failed index file open.  Err: %li\n",rez);
  156.    goto Abend;
  157. }
  158. indexID = OP.handle;
  159.  
  160.  
  161. // Have created and opened both data file and index files.
  162. // The next section inserts record and key with the single call, and removes
  163. // them (or any changes) if and error occured along the way.
  164.  
  165. printf("Display all data accessed (slower results)? (y/N) ");
  166. gets(tmpStr);
  167. if (*tmpStr=='y') display = 1;
  168.  
  169. printf("           Repeat same random key sequence? (Y/n) ");
  170. gets(tmpStr);
  171. if (*tmpStr=='n') sameSequence = 0;
  172.  
  173. printf("  How many records do you want for this test run? ");
  174. gets(tmpStr);
  175. recs2add = atol(tmpStr);
  176. if (recs2add < 1) recs2add = 1;  // would you rather end the test?
  177. if (recs2add > 9999999) recs2add = 1; // why wait around for 10M?  
  178.  
  179. // Add the data records, which are created here, on-the-fly, varying enough
  180. // to make unique records.  The key is inserted for each record added.
  181.  
  182. // setup invariant parts of data record out of loop
  183.  
  184. EmpRec.tag = ' ';                       // set to not-deleted 
  185. strncpy(EmpRec.empID,"000000000",9);    // the key.field 
  186. strcpy(EmpRec.empLN,"YourLastName");    // everyone has the same last name
  187. strcpy(EmpRec.empFN,"YourFirstName");   // everyone has this first name!
  188. strncpy(EmpRec.empHire,"19950618",8);   // YYYYMMDD DBF form, no \0 on date
  189. strcpy(EmpRec.empDept,"MIS");           // everyone works for MIS!
  190.  
  191. // The record construction creates a pretty random SSN number (.empID)
  192. // and that is used as the key -- the key is kept unique (i.e., duplicate
  193. // .empID values are not allowed).  In case of a duplicate (likely given
  194. // the SSN generation technque), the changes made to the database are
  195. // backed out by BULLET.  Another insert is made to cover the count requested.
  196.  
  197. if (sameSequence)
  198.    srand(1);
  199. else
  200.    srand((unsigned)time(0));
  201.  
  202. printf("Inserting %ld recs/keys..  ",recs2add);
  203. time(&startTime);
  204.  
  205. AP.func = INSERT_XB;
  206. AP.handle = indexID;
  207. AP.keyPtr = keyBuffer;
  208. AP.recPtr = &EmpRec;
  209. AP.nextPtr = NULL;
  210.  
  211. for (i = 1; i <= recs2add; i++) {
  212.  
  213.    rndSeqVar = (rand() >> 1) * (rand() >> 2);   // 16383*8191=134193153 max
  214.    sprintf(tmpStr,"%9.9i",rndSeqVar);
  215.    strncpy(EmpRec.empID,tmpStr,9);              // update SSN
  216.  
  217.    // on an INSERT_XB, .recNo has special meaning on input and
  218.    // must be 0 (unless one of two special cases -- see docs)
  219.  
  220.    AP.recNo = 0;
  221.  
  222.    rez = BULLET(&AP);                           // AP. already setup
  223.    if (rez) {
  224.  
  225.       // Since only a single AP pack, on an error rez will be 1 (or -1)
  226.       // this because INSERT_XB is a transaction routine and its return
  227.       // code (rez) is the number of the pack that failed (1 being the first)
  228.       // -- additionally, the number is made negative to identify the error
  229.       // as originating from the data record portion of the insert --
  230.  
  231.       // negative rc means failed during data record add
  232.  
  233.       if (rez < 0) {
  234.          rez = AP.stat;
  235.          printf("Failed during data portion, sequence %ld.  Err: %lu\n",i,rez);
  236.          goto Abend;
  237.       }
  238.  
  239.       // otherwise during index key insert
  240.  
  241.       else {
  242.          rez = AP.stat;
  243.  
  244.          // The random key generated exists, and since field is SSN which is
  245.          // usually unique enough, let's just ignore this (the data record
  246.          // has automatically be removed already) and do another insert to
  247.          // cover the recs2add amount entered by the user (user=you here).
  248.  
  249.          // NOTE: EXB_KEY_EXISTS can be handled by Bullet if during the index
  250.          // create the DUPS_ALLOWED flag were specified, but that would make
  251.          // the key two bytes longer, and since SSN, for practical purposed
  252.          // should be unique (it's said it's not...), just assume this dup
  253.          // never occured.
  254.  
  255.          if (rez == EXB_KEY_EXISTS) {
  256.             rez = 0;
  257.             i--;
  258.          }
  259.          else {
  260.             printf("Failed during index portion, sequence %ld.  Err: %lu\n",i,rez);
  261.             goto Abend;
  262.          }
  263.       }
  264.    }
  265. }
  266. time(&endTime);
  267. printf("took %lu secs.\n",(endTime - startTime));
  268.  
  269.  
  270. memset(keyBuffer,0,sizeof(keyBuffer)); // gives the \0 to the returned key
  271.  
  272. printf(" Accessing %ld keys...     ",recs2add);
  273. if (display) printf("\n");
  274. time(&startTime);
  275. AP.func = FIRST_KEY_XB;
  276. AP.handle = indexID;
  277. AP.keyPtr = keyBuffer;
  278. rez = BULLET(&AP);
  279. i=0;
  280. while (rez==0) {
  281.    i++;
  282.    if (display) printf("%s  %9.9lu\r", keyBuffer, AP.recNo);
  283.    AP.func = NEXT_KEY_XB;
  284.    rez = BULLET(&AP);
  285. };
  286. if (display) printf("\n...");
  287.  
  288. // expected rez is EXB_END_OF_FILE
  289.  
  290. if (rez!=EXB_END_OF_FILE)  {
  291.    printf("Failed KEY access.  Err: %li\n",rez);
  292.    goto Abend;
  293. }
  294. time(&endTime);
  295. printf("took %lu secs. for %ld keys\n",(endTime - startTime),i);
  296.  
  297.  
  298. printf(" Accessing %ld keys+recs...",recs2add);
  299. if (display) printf("\n");
  300. time(&startTime);
  301. AP.func = GET_FIRST_XB;
  302. AP.handle = indexID;
  303. AP.keyPtr = keyBuffer;
  304. AP.recPtr = &EmpRec;
  305. rez = BULLET(&AP);
  306. i=0;
  307. while (rez==0) {
  308.    i++;
  309.    if (display) 
  310.       printf("%s  %9.9lu   %s\r", keyBuffer, AP.recNo, &EmpRec); // to first \0
  311.    AP.func = GET_NEXT_XB;
  312.    rez = BULLET(&AP);
  313. };
  314. if (display) printf("\n...");
  315.  
  316. // expected rez is EXB_END_OF_FILE
  317.  
  318. if (rez!=EXB_END_OF_FILE) {
  319.    printf("Failed GET access.  Err: %li\n",rez);
  320.    goto Abend;
  321. }
  322. time(&endTime);
  323. printf("took %lu secs. for %ld keys & records\n",(endTime - startTime),i);
  324.  
  325. // Fatal errors above come straight to here
  326. Abend:
  327.  
  328. // Close files (index files first then data (recommended but not required))
  329.  
  330. if (indexID) {
  331.    HP.func = CLOSE_INDEX_XB;
  332.    HP.handle = indexID;
  333.    rez = BULLET(&HP);
  334.    if (rez)
  335.       printf("Failed index file close.  Err: %li\n",rez);
  336. }
  337.  
  338. if (dataID) {
  339.    HP.func = CLOSE_DATA_XB;
  340.    HP.handle = dataID;
  341.    rez = BULLET(&HP);
  342.    if (rez)
  343.       printf("Failed data file close.  Err: %li\n",rez);
  344. }
  345.  
  346. return rez;  // program exit
  347. }
  348.  
  349. //------------------------------------
  350. // Init field list items for data file
  351.  
  352. void cx03BuildFieldList(FIELDDESCTYPE fieldList[]) {
  353.  
  354. strcpy(fieldList[0].fieldName, "SSN");
  355. fieldList[0].fieldType = 'C';
  356. fieldList[0].fieldLen = 9;
  357. fieldList[0].fieldDC = 0;
  358.  
  359. strcpy(fieldList[1].fieldName, "LNAME");
  360. fieldList[1].fieldType = 'C';
  361. fieldList[1].fieldLen = 16;
  362. fieldList[1].fieldDC = 0;
  363.  
  364. strcpy(fieldList[2].fieldName, "FNAME");
  365. fieldList[2].fieldType = 'C';
  366. fieldList[2].fieldLen = 16;
  367. fieldList[2].fieldDC = 0;
  368.  
  369. strcpy(fieldList[3].fieldName, "HIRED");
  370. fieldList[3].fieldType = 'D';
  371. fieldList[3].fieldLen = 8;      // date field type must be 8.0
  372. fieldList[3].fieldDC = 0;
  373.  
  374. strcpy(fieldList[4].fieldName, "DEPT");
  375. fieldList[4].fieldType = 'C';
  376. fieldList[4].fieldLen = 6;
  377. fieldList[4].fieldDC = 0;
  378. }
  379.